package com.it.App.realm;

import cn.hutool.core.util.ObjectUtil;
import com.it.App.eneity.User;
import com.it.App.service.PermissionService;
import com.it.App.service.RoleService;
import com.it.App.service.impl.UserServiceImpl;
import com.it.App.token.JwtToken;
import com.it.App.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * @DateTime: 2023/11/28/12:50
 * @注释: 执行授权和认证逻辑，验证用户身份信息
 **/
@Component
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionService permissionService;

    /**
     * 判断是否支持自定义的Token类型
     *
     * @param token 认证信息的Token
     * @return 是否支持该Token类型
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 执行授权逻辑
     *
     * @param principalCollection 当前用户的身份信息集合
     * @return 授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取用户名
        String username = (String) principalCollection.iterator().next();

        // 根据用户名获取用户拥有的角色和权限
        Set<String> roleNames = roleService.getAllRoleNamesByUsername(username);
        Set<String> permissions = permissionService.getAllPermissionByUsername(username);

        // 构建授权信息对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roleNames); // 设置用户角色
        authorizationInfo.setStringPermissions(permissions); // 设置用户权限

        return authorizationInfo;
    }

    /**
     * 执行认证逻辑，验证用户身份信息
     *
     * @param authenticationToken 认证信息的Token
     * @return 认证信息
     * @throws AuthenticationException 认证异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 转换为自定义的JwtToken
        JwtToken jwtToken = (JwtToken) authenticationToken;

        // 从Token中获取用户信息
        String token = (String) jwtToken.getPrincipal();
        Claims claim = JwtUtil.parseJWT(token);
        String username = claim.getId();

        // 根据用户名查询用户信息
        User user = userService.selectUserByName(username);

        // 如果用户不存在，返回null，表示认证失败
        if (ObjectUtil.isNull(user)) {
            return null;
        }

        // 返回认证信息，包括用户名和数据库中的密码
        return new SimpleAuthenticationInfo(username, user.getPassword(), getName());
    }
}

